package com.yizisu.basemvvm.view

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.ViewParent
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.yizisu.basemvvm.R
import com.yizisu.basemvvm.mvvm.mvvm_helper.SingleClickListener
import com.yizisu.basemvvm.utils.dip
import com.yizisu.basemvvm.utils.visible

/**
 * 若红楼梦空，亦初心不变
 * 作者：thinker
 * 包名：android_bull_b.bull.member.thinker.com.androidbullb.utils
 * 时间：2018/12/28 18:02
 * 描述：P：item类型---t:viewHolder
 */
abstract class BaseRcvAdapter<P, T : RecyclerView.ViewHolder> :
    RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private var _datas: MutableList<P>
    /**
     * 是否正在显示正在加载布局
     */
    private var _isAutoLoadMoreShow = false

    constructor() {
        _datas = mutableListOf()
    }

    constructor(initDatas: MutableList<P>? = null) {
        _datas = initDatas ?: mutableListOf()
    }

    val datas: MutableList<P>
        get() = _datas
    /**
     * 设置点击事件
     */
    private var itemClick: ((itemView: View, position: Int, itemData: P) -> Unit)? = null
    /**
     * 长按事件
     */
    private var itemLongClick: ((itemView: View, position: Int, itemData: P) -> Unit)? = null
    /**
     *滚动到最后，用于分页
     */
    private var onScrollEndListener: Function1<MutableList<P>, Unit>? = null

    /**
     * 是否自动加载更多
     */
    private val autoLoadMoreType = -1104

    protected open fun isAutoLoadMore() = false
    /**
     * 获取自定义的加载更多布局
     */
    protected open fun getAutoLoadMoreLayoutRes(): Int = R.layout.default_load_more

    /**
     * 设置点击事件
     */
    private var itemClickId: Int? = null


    /**
     * recyclerView的item的res
     * 为了支持多类型的item
     */
    abstract fun getItemLayoutRes(): Int

    /**
     * recyclerView的item的res
     * 为了支持多类型的item
     */
    open fun getItemLayoutRes(inflater: LayoutInflater, parent: ViewGroup, viewType: Int): Int? =
        null

    /**
     * recyclerView的item的view
     * 如果重写了这个将不会再调用getItemLayoutRes()
     */
    open fun getItemLayoutView(inflater: LayoutInflater, parent: ViewGroup, viewType: Int): View? =
        null

    /**
     * 创建viewHolder
     */
    abstract fun onCreateViewHolder(itemView: View): T

    /**
     * 绑定item
     */
    abstract fun onBindViewHolder(holder: T, position: Int, itemData: P)

    private var loadMoreView: View? = null
    final override fun onCreateViewHolder(
        parent: ViewGroup,
        viewType: Int
    ): RecyclerView.ViewHolder {
        if (isAutoLoadMore() && viewType == autoLoadMoreType) {
            loadMoreView = LayoutInflater.from(parent.context)
                .inflate(getAutoLoadMoreLayoutRes(), parent, false)
            return DefaultLoadMoreHolder(loadMoreView!!)
        }
        val holder = onCreateHolder(parent, viewType)
        setClickEvent(holder)
        return holder
    }

    /**
     * 是否设置点击事件
     * 防止创建过多无用的对象
     */
    private fun setClickEvent(holder: T) {
        itemClick?.let { listener ->
            if (itemClickId != null) {
                holder.itemView.findViewById<View>(itemClickId!!)
                    .setOnClickListener(SingleClickListener {
                        val position = holder.adapterPosition
                        if (position >= 0) {
                            listener.invoke(it, position, datas[position])
                        }
                    })
            } else {
                holder.itemView.setOnClickListener(SingleClickListener {
                    val position = holder.adapterPosition
                    if (position >= 0) {
                        listener.invoke(it, position, datas[position])
                    }
                })
            }
        }
        itemLongClick?.let { listener ->
            if (itemClickId != null) {
                holder.itemView.findViewById<View>(itemClickId!!).setOnLongClickListener {
                    val position = holder.adapterPosition
                    if (position >= 0) {
                        listener.invoke(it, position, datas[position])
                    }
                    true
                }
            } else {
                holder.itemView.setOnLongClickListener {
                    val position = holder.adapterPosition
                    if (position >= 0) {
                        listener.invoke(it, position, datas[position])
                    }
                    true
                }
            }
        }
    }

    open fun onCreateHolder(parent: ViewGroup, viewType: Int): T {
        val inflater = LayoutInflater.from(parent.context)
        //首先调用同new创建的view，如果为null，则再调用下一个方法
        var itemView = getItemLayoutView(inflater, parent, viewType)
        if (itemView == null) {
            val layoutRes = getItemLayoutRes(inflater, parent, viewType)
            itemView = if (layoutRes == null) {
                inflater.inflate(getItemLayoutRes(), parent, false)
            } else {
                inflater.inflate(layoutRes, parent, false)
            }
        }
        return onCreateViewHolder(itemView ?: View(parent.context))
    }

    @Suppress("UNCHECKED_CAST")
    final override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        //如果是含有正在加载的布局直接返回
        if (isAutoLoadMore() && position == datas.count()) {
            if (!_isAutoLoadMoreShow) {
                _isAutoLoadMoreShow = true
                onScrollEndListener?.invoke(_datas)
            }
            return
        }
        when (holder) {
            is DefaultLoadMoreHolder -> {
            }
            else -> {
                val itemData = _datas[position]
                onBindViewHolder(holder as T, position, itemData)
            }
        }
    }


    open fun getViewType(position: Int): Int {
        return 0
    }

    final override fun getItemViewType(position: Int): Int {
        if (isAutoLoadMore() && position == _datas.count()) {
            return autoLoadMoreType
        }
        return getViewType(position)
    }

    /**
     * 设置item点击监听
     */
    fun setOnItemClickListener(
        clickId: Int? = null,
        listener: ((itemView: View, position: Int, itemData: P) -> Unit)
    ) {
        this.itemClick = listener
        this.itemClickId = clickId
    }

    fun setOnItemLongClickListener(
        clickId: Int? = null,
        listener: ((itemView: View, position: Int, itemData: P) -> Unit)
    ) {
        this.itemLongClick = listener
        this.itemClickId = clickId
    }

    /**
     * 设置滑到底部的监听
     */
    fun setOnScrollEndListener(l: Function1<MutableList<in P>, Unit>) {
        this.onScrollEndListener = l
    }

    final override fun getItemCount(): Int {
        if (_datas.isNullOrEmpty()) {
            return 0
        }
        return if (isAutoLoadMore()) {
            _datas.size + 1
        } else {
            _datas.size
        }
    }

    /**
     * 所有数据加载完毕的回调,可以做一下view的改变
     */
    protected open fun onLoadMoreEnd(loadMoreView: View?) {
        if (loadMoreView is ViewGroup && getAutoLoadMoreLayoutRes() == R.layout.default_load_more) {
            loadMoreView.postDelayed({
                loadMoreView.removeViewAt(1)
                loadMoreView.getChildAt(0).visible()
            }, 800)
        }
    }

    /**
     * 加载更多调用这个方法
     * isEnd:所有数据加载完毕
     */
    fun loadMoreFinish(newList: MutableList<P>?, isEnd: Boolean = false) {
        if (isEnd) {
            _isAutoLoadMoreShow = true
            onLoadMoreEnd(loadMoreView)
        } else {
            _isAutoLoadMoreShow = false
        }
        loadMoreList(newList)
    }

    /**
     * 刷新列表
     */
    fun refreshListByDiff(
        newList: MutableList<P>,
        areItemTheSame: ((old: P?, new: P?) -> Boolean) = { _, _ -> false },
        areContentsTheSame: ((old: P?, new: P?) -> Boolean) = { _, _ -> false }
    ) {
        val result = DiffUtil.calculateDiff(
            BaseDiffCall(
                _datas,
                newList,
                areItemTheSame,
                areContentsTheSame
            ), true
        )
        result.dispatchUpdatesTo(this)
        _datas.clear()
        _datas.addAll(newList)
    }

    /**
     * 无脑刷新
     * 有时候高效刷新动画有问题，可以尝试这个
     */
    fun refreshList(newList: MutableList<P>?) {
        _datas.clear()
        newList?.let {
            _datas.addAll(it)
        }
        notifyDataSetChanged()
    }

    /**
     * 加载更多,在原来基础上新插入数据
     * 自动加载更多，不可以调用此方法
     */
    fun loadMoreList(newList: MutableList<P>?) {
        newList ?: return
        val startPosition = _datas.size
        _datas.addAll(newList)
        notifyItemRangeInserted(startPosition, newList.size)
    }

    /**
     * 清除数据
     */
    fun clearDatas() {
        if (_datas.isNotEmpty()) {
            _datas.clear()
            notifyItemRangeRemoved(0, _datas.count())
        }
    }

    /**
     * 高效刷新
     */
    inner class BaseDiffCall(
        val old: MutableList<P>?,
        val new: MutableList<P>?,
        private val areItemSame: ((old: P?, new: P?) -> Boolean),
        private val areContentSame: ((old: P?, new: P?) -> Boolean)
    ) : DiffUtil.Callback() {

        override fun getOldListSize(): Int = old?.size ?: 0

        override fun getNewListSize(): Int = new?.size ?: 0

        override fun areItemsTheSame(p0: Int, p1: Int): Boolean {
            return areItemSame.invoke(old?.get(p0), new?.get(p1))
        }

        override fun areContentsTheSame(p0: Int, p1: Int): Boolean {
            return areContentSame.invoke(old?.get(p0), new?.get(p1))
        }
    }

    internal class DefaultLoadMoreHolder(item: View) : RecyclerView.ViewHolder(item)
}





